// THIS FILE FINDS THE LAMBDAS (THE MC OF THE MARGINAL PLANT)
// ASSUMING GERMANY-WIDE DISPATCH (ROBUSTNESS 2)
**************************
	
set more off
cd "${PATH}/data"

use "entsoe.dta", clear

drop eventtime 

// KEEP OBSERVATIONS FOR 2015 and 2016 ONLY	
drop if yofd(daily) > 2016


// Ajustment for fossiloil: TenneT has one plant running at 1 MWH capacity always from March 2016 onwards 
* Do only consider as marginal source if prodcution >1
replace fossiloil = 0 if fossiloil == 1


// SORT GENERATION SOURCES WITH INCREASING COST
order windoffshore windonshore solar otherrenewable marine hydrowaterreservoir hydrorunofriverandpoundage hydropumpedstorage geothermal waste biomass nuclear fossilbrowncoallignite fossilcoalderivedgas fossilhardcoal fossilgas fossilpeat fossiloilshale fossiloil 


// 50 HZ, special case: Adjustment in fossiloil  //
// REPLACE MARGINAL TECHNOLOGY WITH THE SECOND MOST EXPENSIVE IN 50HZ as OIL production linked to refinery (always running and not responding to prices)
** Here, as only interested in marginal source, replace as zero 
replace fossiloil = 0 if TSO =="50Hertz"


// Collapse [sum over all 4 TSOs]
collapse (sum) windoffshore-fossiloil other (mean) cost_MWH_crude_oil - emission_MWH_v2_brown_coal, by(time_utc)


preserve 
// Obtain Marginal Technologies (note that this is different from step-size below)

// COMMENT: treat fossil coal defived gas as gas in this sample as to determine "min produciton capacities" // ALternatively add to fossilhardcoal production
gen gas = fossilgas + fossilcoalderivedgas 
gen waste_biomass = waste + biomass
*replace fossilhardcoal = fossilhardcoal 

foreach v of varlist fossilbrowncoallignite nuclear fossilhardcoal gas fossiloil waste_biomass hydrorunofriverandpoundage hydropumpedstorage {
	
su `v.' if `v' !=0 ,d
}

** IDENTIFY MARGINAL PLANTS: 
// Adjustments based on must-run capacities (Consentec, 2016)
/*
 Fuel Type				Capacity in MW		Approx. percentile of pos. values (see su,d below)
			
lignite 				8526.3 				<5
uranium 				6981.7				10 
coal					2587.3  			10
gas						1901.3				>50, <75  // POTENTIAL OUTLIER, USE P25 AS MAX OBSERVED IN OTHER TECHNOLOGIES
oil						62.0 				<25
garbage 				148.3 				<1
run-of-the-river 		118.3				<1
pumped-storage 			70.3				<25
seasonal store 		 	18.3 				X
other					869.0				X
*/ 

replace fossilbrowncoallignite = 0 if fossilbrowncoallignite <= 8526.3
replace nuclear = 0 if nuclear <= 6981.7
replace fossilhardcoal = 0 if fossilhardcoal <= 2587.3
replace gas = 0 if gas <= 932 // corresponds to p25 (max value observed for other technologies)
replace waste_biomass = 0 if waste_biomass <= 148.3
replace hydrorunofriverandpoundage = 0 if hydrorunofriverandpoundage <= 118.3
replace hydropumpedstorage = 0 if hydropumpedstorage <=70.3


// FIND MARGINAL SOURCE 
* local ele_type "windoffshore windonshore solar otherrenewable marine hydrowaterreservoir hydrorunofriverandpoundage hydropumpedstorage geothermal waste biomass nuclear fossilbrowncoallignite fossilcoalderivedgas fossilhardcoal fossilgas fossilpeat fossiloilshale fossiloil" 

local ele_type "windoffshore windonshore solar otherrenewable marine hydrowaterreservoir hydrorunofriverandpoundage hydropumpedstorage geothermal waste_biomass nuclear fossilbrowncoallignite fossilhardcoal gas fossilpeat fossiloilshale fossiloil" 
local types: word count `ele_type'


forvalues n = 1/`types' {
	local source: word `n' of `ele_type'  
	gen marg_`n' = "`source'" if !missing(`source') & `source'!=0
} 

gen marginal = ""
foreach n of numlist `types'(-1)1 {
	replace marginal = marg_`n' if !missing(marg_`n') & missing(marginal)
}

drop marg_*

keep time_utc marginal 

tempfile temp1
save `temp1'
restore


***********************************
** Add marginal source to file (without setting to zero must-run capacities)
merge 1:1 time_utc using `temp1'
drop _merge // all merged, no missing time intervals 

// Adjust variable names in line with main variables
replace marginal = "fossilgas" if marginal == "gas"
replace marginal = "biomass" if marginal == "waste_biomass"

***********************
// TABLE WITH 

tab marginal,gen(m_) sort
***********************


** REPLICATE HERE LAMBDAS_V1.do

// MARGINAL COSTS ($/MWH)
gen marginal_cost = 0 
replace marginal_cost = 5.1 if marginal == "nuclear" // source: ENTSO-e TYNDP 2018 modeling data as in Golub et al. 
replace marginal_cost = 6 if marginal == "biomass" // allow biomass to be marginal: assign positive value higher than nuclear in line with industry reports
replace marginal_cost = 11.3 if marginal == "fossilbrowncoallignite"  // Brown Coal Report: est. cost of extraction in Germany
replace marginal_cost = cost_MWH_coal if marginal == "fossilhardcoal" // Based on international markets
replace marginal_cost = cost_MWH_ng if marginal == "fossilgas" // Based on international markets
replace marginal_cost = cost_MWH_crude_oil if marginal == "fossiloil" // Based on international markets


// MARGINAL EMISSIONS (t/MWH)
gen marginal_emissions = 0 
replace marginal_emissions = emission_MWH_coal if marginal == "fossilhardcoal"
replace marginal_emissions = 1.148 if marginal == "fossilbrowncoallignite" 
replace marginal_emissions = emission_MWH_ng if marginal == "fossilgas" 
replace marginal_emissions = emission_MWH_crude_oil if marginal == "fossiloil"



// Step length in line with technologies 
* Generate groups (main steps) in line with categories used in Supply_Demand_All_TSOs_analysis:
egen step_0 = rowtotal(windoffshore windonshore solar otherrenewable marine hydrowaterreservoir hydrorunofriverandpoundage hydropumpedstorage geothermal)
gen step_1 = nuclear
egen step_2 = rowtotal(waste biomass)
gen step_3 = fossilbrowncoallignite
egen step_4 = rowtotal(fossilcoalderivedgas fossilhardcoal)
egen step_5 = rowtotal(fossilgas fossilpeat)
egen step_6 = rowtotal(fossiloilshale fossiloil)
mvencode step_*, mv(0) override // TSOs without these technologies



// COMPUTE EXPECTED VALUE OF DERIVATIVE OF AS WRT R
replace time_utc = time_utc - msofhours(1)
** DO same time adjustment as originally in file PVoutput_analysis - 
// sort time_utc TSO
// br time_utc TSO solar_gen solar

merge 1:m  time_utc using "data_15min"
keep if _merge == 3
drop _merge

// Need to merge the cluster for load 
gen date = dofc(time_utc)
gen hour = hh(time_utc)

merge m:1 date hour using "data15min_cluster_TSO_joint.dta", keepusing(kload)
// data15min_cluster_TSO_joint, clusters load Germany-wide
keep if _merge ==3 
drop _merge


*****************************************************
// CALCULATE PRICE AT GERMANY WIDE SOLAR PRODUCTION AND LOAD

*****************************************************

// UPDATED MARGINAL EFFECTS OF ANCILLARY SERVICES  // 
** NEED TO USE GERMANY WIDE FIGURES


// Derivatives of above regression model wrt solar
gen dAS_dR = 21.06 +  ( 0.000167) * 2 * solar_gen_DE + ///
	(-4.69e-10) * 3 * solar_gen_DE^2  + (-0.000718) * load_DE + ///
	 ( 5.95e-09) * load_DE^2 + (-2.25e-09) * 2 * solar_gen_DE * load_DE if kload == 1
	

replace dAS_dR = -6.348 + (-0.000231) * 2 * solar_gen_DE + ///
	(-3.21e-09) * 3 * solar_gen_DE^2  + (0.000316) * load_DE + ///
	  (-4.01e-09) * load_DE^2 + (6.37e-09) * 2 * solar_gen_DE * load_DE if kload == 2 		  

replace dAS_dR = 0.273 + 0.0000246  * 2 * solar_gen_DE + ///
	(3.16e-09) * 3 * solar_gen_DE^2  + (-0.0000224) * load_DE + ///
	   3.20e-10  * load_DE^2 + (-1.47e-09) * 2 * solar_gen_DE * load_DE if kload == 3 
	
		  	  
saveold  "lambda_15min_robust2", replace
*****************	  
